home *** CD-ROM | disk | FTP | other *** search
- /* XLISP evaluation module */
-
- #ifdef CI_86
- #include "a:stdio.h"
- #include "xlisp.h"
- #endif
-
-
- #ifdef AZTEC
- #include "a:stdio.h"
- #include "a:setjmp.h"
- #include "xlisp.h"
- #endif
-
- #ifdef unix
- #include <stdio.h>
- #include <setjmp.h>
- #include <xlisp.h>
- #endif
-
-
- /* global variables */
- struct node *xlstack;
-
- /* trace stack */
- static struct node *trace_stack[TDEPTH];
- static int trace_pointer;
-
- /* external variables */
- extern struct node *xlenv;
-
- /* local variables */
- static struct node *slash;
-
- /* forward declarations (the extern hack is for decusc) */
- extern struct node *evlist();
- extern struct node *evsym();
- extern struct node *evfun();
-
-
- /***************************************
- * eval - the builtin function 'eval' *
- ***************************************/
-
- static struct node *eval(args)
- struct node *args;
- {
- struct node *oldstk,expr,*val;
-
- oldstk = xlsave(&expr,NULL); /* Create new stack frame */
-
- expr.n_ptr = xlevarg(&args); /* Expression to evaluate */
- xllastarg(args); /* No more args ! */
-
- val = xleval(expr.n_ptr); /* Do evaluation */
-
- xlstack = oldstk; /* Restore old stack frame */
- return (val);
- }
-
- /******************************************
- * xleval - evaluate an xlisp expression *
- ******************************************/
-
-
- struct node *xleval(expr)
- struct node *expr;
- {
- if (expr == NULL) /* Null evaluates to null */
- return (NULL);
-
- switch (expr->n_type) /* Value type */
- {
- case LIST:
- return (evlist(expr));
-
- case SYM:
- return (evsym(expr));
-
- case INT:
- case STR:
- case SUBR:
- case REAL:
- return (expr);
-
- default:
- xlfail("can't evaluate expression");
- }
- }
-
-
-
- /*************************************
- * xlsave - save nodes on the stack *
- *************************************/
-
- struct node *xlsave(n)
- struct node *n;
- {
- struct node **nptr,*oldstk;
-
- oldstk = xlstack; /* Save old stack pointer */
-
- for (nptr = &n; *nptr != NULL; nptr++) /* Save for each node */
- {
- (*nptr)->n_type = LIST;
- (*nptr)->n_listvalue = NULL;
- (*nptr)->n_listnext = xlstack;
- xlstack = *nptr;
- }
-
- return (oldstk); /* Return old stack pointer */
- }
-
-
-
- /*****************************
- * evlist - evaluate a list *
- *****************************/
-
- static struct node *evlist(nptr)
- struct node *nptr;
- {
- struct node *oldstk,fun,args,*val;
-
- oldstk = xlsave(&fun,&args,NULL); /* Creat a stack frame */
-
- fun.n_ptr = nptr->n_listvalue; /* Get function and arg list */
- args.n_ptr = nptr->n_listnext;
-
- tpush(nptr); /* Add trace entry */
-
- if ((fun.n_ptr = xleval(fun.n_ptr)) == NULL) /* Evaluate first expression */
- xlfail("null function");
-
- switch (fun.n_ptr->n_type) /* Evaluate function */
- {
- case SUBR:
- val = (*fun.n_ptr->n_subr)(args.n_ptr);
- break;
-
- case LIST:
- val = evfun(fun.n_ptr,args.n_ptr);
- break;
-
- case OBJ:
- val = xlsend(fun.n_ptr,args.n_ptr);
- break;
-
- default:
- xlfail("bad function");
- }
-
- xlstack = oldstk; /* Restore old stack frame */
- tpop(); /* Remove trace entry */
- return (val); /* and return result value */
- }
-
-
-
- /******************************
- * evsym - evaluate a symbol *
- ******************************/
-
- static struct node *evsym(sym)
- struct node *sym;
- {
- struct node *lptr;
-
- if ((lptr = xlobsym(sym)) != NULL) /* Check for current object */
- return (lptr->n_listvalue);
- else
- return (sym->n_symvalue);
- }
-
-
- /********************************
- * evfun - evaluate a function *
- ********************************/
-
- static struct node *evfun(fun,args)
- struct node *fun,*args;
- {
- struct node *oldenv,*oldstk,cptr,*fargs,*val;
-
- oldstk = xlsave(&cptr,NULL); /* Creat a new stack frame */
-
- /* get the formal argument list */
- if ((fargs = fun->n_listvalue) != NULL && fargs->n_type != LIST)
- xlfail("bad formal argument list");
-
- oldenv = xlenv; /* Bind the formal parameters*/
- xlabind(fargs,args);
- xlfixbindings(oldenv);
-
- for (cptr.n_ptr = fun->n_listnext; cptr.n_ptr != NULL; ) /* execute */
- val = xlevarg(&cptr.n_ptr);
-
- xlunbind(oldenv); /* Restore environment */
- xlstack = oldstk; /* ..then the stack frame */
- return (val); /* ...and return result */
- }
-
-
-
- /************************************************
- * xlabind - bind the arguments for a function *
- ************************************************/
-
- xlabind(fargs,aargs)
- struct node *fargs,*aargs;
- {
- struct node *oldstk,farg,aarg,val;
-
- oldstk = xlsave(&farg,&aarg,&val,NULL); /* Create a stack frame */
-
- farg.n_ptr = fargs; /* Initialze the pointers */
- aarg.n_ptr = aargs;
-
- while (farg.n_ptr != NULL && aarg.n_ptr != NULL) /* evaluate and bind */
- {
- if (farg.n_ptr->n_listvalue == slash) /* Check for local separator*/
- break;
-
- val.n_ptr = xlevarg(&aarg.n_ptr); /* Evaluate the arg */
- xlbind(farg.n_ptr->n_listvalue,val.n_ptr); /* ..and bind to formal */
-
- farg.n_ptr = farg.n_ptr->n_listnext; /* Move pointer ahead */
- }
-
- /* check for local variables */
- if (farg.n_ptr != NULL && farg.n_ptr->n_listvalue == slash)
- while ((farg.n_ptr = farg.n_ptr->n_listnext) != NULL)
- xlbind(farg.n_ptr->n_listvalue,NULL);
-
- xlstack = oldstk; /* Restore old stack frame */
-
- if (farg.n_ptr != aarg.n_ptr) /* Check for correct # */
- xlfail("incorrect number of arguments to a function");
- }
-
-
-
- /************************************
- * xlfail - error handling routine *
- ************************************/
-
- xlfail(err)
- char *err;
- {
- printf("error: %s\n",err); /* Print the error message */
- xlunbind(NULL); /* Unbind any bound symbols */
- xltin(TRUE); /* Restore input to terminal */
- trace(); /* Do the back trace */
- trace_pointer = -1;
- xlabort(); /* Restart */
- }
-
-
- /********************************************
- * tpush - add an entry to the trace stack *
- ********************************************/
-
- static tpush(nptr)
- struct node *nptr;
- {
- if (++trace_pointer < TDEPTH)
- trace_stack[trace_pointer] = nptr;
- }
-
-
-
- /*********************************************
- * tpop - pop an entry from the trace stack *
- *********************************************/
-
- static tpop()
- {
- trace_pointer--;
- }
-
-
-
- /****************************
- * trace - do a back trace *
- ****************************/
-
- static trace()
- {
- for (; trace_pointer >= 0; trace_pointer--)
- if (trace_pointer < TDEPTH)
- {
- xlprint(trace_stack[trace_pointer],TRUE);
- putchar('\n');
- }
- }
-
-
-
- /***************************************
- * xleinit - initialize the evaluator *
- ***************************************/
-
- xleinit()
- {
- slash = xlenter("/"); /* the local variable separator */
-
- trace_pointer = -1; /* Initialize debugging */
-
- xlsubr("eval",eval); /* Built in functions from this module */
- }